/**
 * Copyright (c) 2015-present, Facebook, Inc.
 * All rights reserved.
 *
 * This source code is licensed under the license found in the LICENSE file in
 * the root directory of this source tree.
 *
 * @flow
 * @format
 */

import type {LegacyProcessMessage} from 'nuclide-commons/process';
import type {DebugBridgeConfig} from '../types';

import {Observable} from 'rxjs';
import {observeProcess, runCommand} from 'nuclide-commons/process';

function getPortArg(port: ?number): Array<string> {
  return port != null ? ['-P', String(port)] : [];
}

export class DebugBridge {
  static configObs: Observable<DebugBridgeConfig>;

  _device: string;

  constructor(device: string) {
    this._device = device;
  }

  runShortCommand(...command: string[]): Observable<string> {
    return this.constructor.configObs.switchMap(config =>
      runCommand(
        config.path,
        this._getDeviceArg(this._device)
          .concat(getPortArg(config.port))
          .concat(command),
      ),
    );
  }

  runLongCommand(...command: string[]): Observable<LegacyProcessMessage> {
    // TODO(T17463635)
    return this.constructor.configObs.switchMap(config =>
      observeProcess(
        config.path,
        this._getDeviceArg(this._device)
          .concat(getPortArg(config.port))
          .concat(command),
        {
          killTreeWhenDone: true,
          /* TODO(T17353599) */ isExitError: () => false,
        },
      ).catch(error => Observable.of({kind: 'error', error})),
    ); // TODO(T17463635)
  }

  _getDeviceArg(device: string): string[] {
    return device !== '' ? ['-s', device] : [];
  }

  static getDevices(): Observable<Array<string>> {
    return this.configObs.switchMap(config =>
      runCommand(
        config.path,
        getPortArg(config.port).concat(['devices']),
      ).map(stdout =>
        stdout
          .split(/\n+/g)
          .slice(1)
          .filter(s => s.length > 0 && !s.trim().startsWith('*'))
          .map(s => s.split(/\s+/g))
          .filter(a => a[0] !== '')
          .map(a => a[0]),
      ),
    );
  }
}
